local VERSION = tonumber(("$Revision: 207 $"):match("%d+"))

local _G = getfenv(0)

local friends = AceLibrary("LibFriends-1.0")

local L = AceLibrary("AceLocale-2.2"):new("AuldLangSyne_Sync")

local AuldLangSyne = AuldLangSyne
local Sync
if AuldLangSyne then
	Sync = AuldLangSyne:NewModule("Sync", "AceEvent-2.0", "AceConsole-2.0")
	if AuldLangSyne.revision < VERSION then
		AuldLangSyne.version = "r" .. VERSION
		AuldLangSyne.revision = VERSION
		AuldLangSyne.date = ("$Date: 2008-04-25 18:38:06 +0000 (Fri, 25 Apr 2008) $"):match("%d%d%d%d%-%d%d%-%d%d")
	end
else
	Sync = AceLibrary("AceAddon-2.0"):new("AceEvent-2.0", "AceConsole-2.0", "AceDB-2.0")
	AuldLangSyne_Sync = Sync -- since this isn't a module in this branch, global for access
end

--local startState_add = {}
--local startState_remove = {}

function Sync:OnInitialize(name)
	local chardefaults = {
		sync = false,
	}
	local realmdefaults = {
		add_friends = {
			["*"] = {},
		},
		remove_friends = {
			["*"] = {},
		},
	}
	if AuldLangSyne then
		self.db = AuldLangSyne:AcquireDBNamespace("Sync")
		AuldLangSyne:RegisterDefaults("Sync", "char", chardefaults)
		AuldLangSyne:RegisterDefaults("Sync", "realm", realmdefaults)
	else
		self:RegisterDB("AuldLangSyneSyncDB")
		self:RegisterDefaults("realm", realmdefaults)
		self:RegisterDefaults("char", chardefaults)
	end
	
	self.menu = {
		handler = Sync,
		name = L["Sync"], type = "toggle",
		desc = L["Synchronize the friends lists of all your characters on this realm."],
		get = function() return self.db.char.sync end,
		set = function(t) self.db.char.sync = t; if t then self:SyncFriends() end end,
	}
	
	self:RegisterChatCommand({'/synctoggle',}, self.menu)
	
	--Stolen from AceDB.
	local _,race = UnitRace("player")
	if race == "Orc" or race == "Scourge" or race == "Troll" or race == "Tauren" or race == "BloodElf" then
		self.faction = "0"
	else
		self.faction = "1"
	end
	
	if AuldLangSyne and AuldLangSyne.db.realm.add_friends then
		self.db.realm.add_friends = AuldLangSyne.db.realm.add_friends
		AuldLangSyne.db.realm.add_friends = nil
		self.db.realm.remove_friends = AuldLangSyne.db.realm.remove_friends
		AuldLangSyne.db.realm.remove_friends = nil
		self.db.realm.sync = nil
	end
	
	--[[for k,v in pairs(self.db.realm.add_friends) do
		startState_add[k] = v
	end
	for k,v in pairs(self.db.realm.remove_friends) do
		startState_remove[k] = v
	end--]]
end

function Sync:OnEnable(first)
	friends.RegisterCallback(self, "Added")
	friends.RegisterCallback(self, "Removed")
	self:RegisterEvent("CHAT_MSG_SYSTEM")
	
	if self.db.char.sync then
		self:SyncFriends()
	end
end

-- Friend syncing

local friendCache = {}
local currentFriend

function Sync:AddFriend(name)
	currentFriend = name
	AddFriend(name)
end

function Sync:RemoveFriend(name)
	currentFriend = (type(name) == "number") and GetFriendInfo(name) or name
	RemoveFriend(name)
end

function Sync:SyncFriends()
	local friends = self.db.realm.add_friends[self.faction]
	local remove = self.db.realm.remove_friends[self.faction]
	
	--First, absorb any new friends from this character, and remove any friends scheduled for removal.
	local numFriends = GetNumFriends()
	if #friendCache ~= numFriends then
		for i=1, numFriends do
			local name = GetFriendInfo(i)
			if name then
				friendCache[name] = true
				if remove[name] then
					return self:RemoveFriend(name)
				else
					friends[name] = true
				end
			end
		end
	end
	
	--Now add any friends this character doesn't have yet.
	local playername = UnitName("player")
	for name in pairs(friends) do
		if playername ~= name and not friendCache[name] then
			return self:AddFriend(name)
		end
	end
	
	self:StopSync()
end

function Sync:StopSync()
	--And clear that helpful friendCache
	for name in pairs(friendCache) do
		friendCache[name] = nil
	end
	currentFriend = nil
end

function Sync:Added(event, name)
	if self.db.char.sync and name ~= UnitName("player") then
		self.db.realm.add_friends[self.faction][name] = true
		self.db.realm.remove_friends[self.faction][name] = nil -- just in case
	end
	if currentFriend then
		self:SyncFriends()
	end
end

local deleteAlert
function Sync:Removed(event, name)
	if self.db.char.sync and self.db.realm.add_friends[self.faction][name] ~= nil then
		self.db.realm.add_friends[self.faction][name] = nil
		self.db.realm.remove_friends[self.faction][name] = true
	end
	if deleteAlert then
		self:Print(name .. " was removed from your friends list because they no longer exist.")
		deleteAlert = nil
	end
	if currentFriend then
		self:SyncFriends()
	end
end

local trigger_remove = {
	[ERR_FRIEND_LIST_FULL] = true,
	[ERR_FRIEND_WRONG_FACTION] = true,
	[ERR_FRIEND_NOT_FOUND] = true,
}
local trigger_abort = {
	[ERR_FRIEND_DB_ERROR] = true,
	[ERR_FRIEND_ERROR] = true,
	[ERR_FRIEND_LIST_FULL] = true,
}
function Sync:CHAT_MSG_SYSTEM(msg)
	if msg == ERR_FRIEND_DELETED then
		deleteAlert = true
	elseif currentFriend then
		if trigger_remove[msg] then
			self.db.realm.add_friends[self.faction][currentFriend] = nil
			self:Print(currentFriend .. " removed from sync list.  Sync continuing.")
		elseif trigger_abort[msg] then
			self:StopSync()
			self:Print("Sync aborted due to errors.")
		end
	end
end

